#include <stdlib.h>
#include <string.h>

#include "llist.h"

int llisthead_init(llist_t **mylist, int size)
{
	*mylist = malloc(sizeof(llist_t));
	if (NULL == *mylist)
		return -1;
	(*mylist)->head.prev = &(*mylist)->head;
	(*mylist)->head.next = &(*mylist)->head;
	(*mylist)->size = size;

	return 0;
}

int llist_empty(const llist_t *mylist)
{
	return mylist->head.prev == &mylist->head && mylist->head.next == &mylist->head;
}

// 创建新的结点
static struct node_st *__create_node(const void *data, int size)
{
	struct node_st *me = NULL;

	me = malloc(sizeof(struct node_st) + size);
	if (NULL == me)
		return NULL;
	memcpy(me->data, data, size);
	me->prev = me->next = me;

	return me;
}

// 插入到指定位置
static int __insert(struct node_st *p, struct node_st *n, struct node_st *cur)
{
	cur->prev = p;
	cur->next = n;
	p->next = cur;
	n->prev = cur;	
}

int llist_insert(llist_t *mylist, const void *data)
{
	struct node_st *cur = NULL;

	cur = __create_node(data, mylist->size);
	if (NULL == cur)
		return -1;
	__insert(&mylist->head, mylist->head.next, cur);

	return 0;
}

int llist_insert_tail(llist_t *mylist, const void *data)
{
	struct node_st *cur = NULL;

	cur = __create_node(data, mylist->size);
	if (NULL == cur)
		return -1;
	__insert(mylist->head.prev, &mylist->head, cur);

	return 0;
}

// 查找指定结点
static struct node_st *__find(const llist_t *mylist, const void *key, cmp_t cmp)
{
	struct node_st *f;

	for (f = mylist->head.next; f != &mylist->head; f = f->next)
		if (cmp(f->data, key) == 0)
			return f;

	return NULL;
}

// 删除del指针指向的结点
static int __delete(struct node_st **d)
{
	struct node_st *del = *d;

	del->prev->next = del->next;
	del->next->prev = del->prev;
	del->prev = del->next = NULL;
	free(del);
	*d = NULL; // f

	return 0;
}

int llist_delete(llist_t *mylist, const void *key, cmp_t cmp)
{
	struct node_st *f = __find(mylist, key, cmp);
	if (NULL == f)
		return -1;
	__delete(&f);

	return 0;
}

int llist_fetch(llist_t *mylist, const void *key, cmp_t cmp, void *data){
	
	struct node_st *f = __find(mylist, key, cmp);
	if (NULL == f)
		return -1;
	memcpy(data, mylist->head.next->data, mylist->size);
	__delete(&f);


	return 0;
}

void llist_traval(const llist_t *mylist, pri_t pri)
{
	struct node_st *p;

	for (p = mylist->head.next; p != &mylist->head; p = p->next)
		pri(p->data);
}

static int __alway_cmp(const void *data, const void *key)
{
	return 0;
}

void llist_destroy(llist_t **mylist)
{
	if (*mylist == NULL)
		return ;
	
	while (!llist_empty(*mylist)) {
		llist_delete(*mylist, NULL, __alway_cmp);
	}
	free(*mylist);
	*mylist = NULL;
}


int llist_have_cycle(const llist_t *mylist){
	if(llist_empty(mylist)) return 0;
	struct node_st *fast = mylist->next;
	struct node_st *slow = mylist->next;

	while(fast != NULL && fast->next != NULL){
		slow = slow->next;
		fast = fast->next->next;
		if(slow == fast)return 1:
	}
	return 0;
}

